﻿using System;
using System.Linq;
using CollectionExtensions.Extensions;
using OrangeProject.ReactiveList.Core.Client;
using OrangeProject.ReactiveList.Core.Communication;
using OrangeProject.ReactiveList.Core.Entities;
using OrangeProject.ReactiveList.RabbitMQTransportCore;
using RabbitMQ.Client;

namespace ERP_Server
{
    class Program
    {
        static void Main(string[] args)
        {
            var factory = new ConnectionFactory
            {
                HostName = "192.168.1.128",
                Port = 5672,
                UserName = "orange-project",
                Password = "orange-project"
            };

            var connection = factory.CreateConnection();
            var dataContext = new MyDataContext(new RabbitMqTransportCore("Example", connection, WorkMode.Client));

            dataContext.Persons.Add(new Person(dataContext)
            {
                Name = new Name(dataContext)
                {
                    Ug = "مۇختەر",
                    En = "yeganaaa",
                    Zh = "Mu he ta er"
                },
                Age = 25
            });
            
            dataContext.SaveChanges(() =>
            {
                var name = dataContext.Names.First();
                name.Zh = "Name Changed";
                dataContext.Names.AttachUpdates(name);
                dataContext.SaveChanges(() =>
                {
                    dataContext.Names.ForEach(n =>
                    {
                        Console.WriteLine(n.Zh);
                    });
                });
            });
        }
    }

    
    public abstract class Entity : IEntity
    {
        public abstract String Id { get; set; }
        public MyDataContext DataContext { get; set; }

        public Entity(MyDataContext _dataContext)
        {
            DataContext = _dataContext;
        }
    }

    public class Name : Entity
    {
        public String Ug { get; set; }
        public String En { get; set; }
        public String Zh { get; set; }

        public Name(MyDataContext _dataContext) : base(_dataContext)
        {
        }

        public override string Id { get; set; } = Guid.NewGuid().ToString();
    }

    public class Person : Entity
    {
        public Name Name
        {
            get => DataContext.Names.Single(name => name.Id == __Name);
            set
            {
                if (DataContext.Names.All(name => name.Id != value.Id)) DataContext.Names.Add(value);
                __Name = value.Id;
            }
        }

        public String __Name { get; set; }
        public Byte Age { get; set; }

        public Person(MyDataContext _dataContext) : base(_dataContext)
        {
        }

        public override string Id { get; set; } = Guid.NewGuid().ToString();
    }

    public class MyDataContext : DataContext
    {
        public ReactiveList<Person> Persons { get; }
        public ReactiveList<Name> Names { get; }

        public MyDataContext(ITransportCore transportCore) : base(transportCore)
        {
            Persons = new ReactiveList<Person>(this, list => new Person(this),  "Persons", (oldValue, newValue) =>
                {
                    oldValue.Name = newValue.Name;
                    oldValue.Age = newValue.Age;
                }
                
            );
            Lists.Add(Persons);

            Names = new ReactiveList<Name>(this, list => new Name(this), "Names", (oldValue, newValue) =>
            {
                oldValue.En = newValue.En;
                oldValue.Ug = newValue.Ug;
                oldValue.Zh = newValue.Zh;
            });
            Lists.Add(Names);
        }
    }
}

